package base

import (
	"fmt"
	"net"
	"zinx/interfa"
	"zinx/utils"
	"zinx/zlog"
)

// iServer接口实现，定义Server服务类
type Server struct {
	Name      string
	IPVersion string
	IP        string
	Port      int
	// 当前Server由用户绑定的回调router
	msgHandle   interfa.IMsgHandle
	ConnMgr     interfa.IConnManger
	OnConnStart func(conn interfa.IConnection)
	OnConnStop  func(conn interfa.IConnection)
	exitChan    chan struct{}
	packet      interfa.IDataPack
}

func NewServer(opts ...Option) interfa.IServer {
	printServerInfo()
	s := &Server{
		Name:      utils.GlobalObject.Name,
		IPVersion: "tcp4",
		IP:        utils.GlobalObject.Host,
		Port:      utils.GlobalObject.TcpPort,
		msgHandle: NewMsgHandle(),
		ConnMgr:   NewConnManager(),
		exitChan:  nil,
		packet:    Factory().NewPack(interfa.ZinxDataPack),
	}

	for _, opt := range opts {
		opt(s)
	}
	return s
}

func (s *Server) Start() {
	s.exitChan = make(chan struct{})
	go func() {
		// 启动worker工作池机制
		s.msgHandle.StartWorkerPool()

		addr, err := net.ResolveTCPAddr(s.IPVersion, fmt.Sprintf("%s:%d", s.IP, s.Port))
		if err != nil {
			zlog.Error("Resolve Tcp Addr Err: ", err)
			return
		}

		// 监听
		listenner, err := net.ListenTCP(s.IPVersion, addr)
		if err != nil {
			zlog.Error("Listen ", s.IPVersion, " Err: ", err)
			return
		}

		var cid uint32 = 0
		go func() {
			for {
				// 阻塞等待客户端连接
				conn, err := listenner.AcceptTCP()
				if err != nil {
					zlog.Error("Accept Err: ", err)
					continue
				}

				// 设置服务器最大连接控制,如果超过最大连接，那么则关闭此新的连接
				if s.ConnMgr.Len() >= utils.GlobalObject.MaxConn {
					conn.Close()
					continue
				}

				dealConn := NewConntion(s, conn, cid, s.msgHandle)
				cid++
				go dealConn.Start()
			}
		}()

		select {
		case <-s.exitChan:
			if err := listenner.Close(); err != nil {
				zlog.Error("Listenner close err ", err)
			}
		}
	}()
}

func (s *Server) Stop() {
	zlog.Debug("[STOP] Server Name: ", s.Name)
	s.ConnMgr.ClearConn()
	s.exitChan <- struct{}{}
	close(s.exitChan)
}

func (s *Server) Serve() {
	s.Start()
	select {}
}

func (s *Server) AddRouter(msgId uint32, router ...interfa.RouterHandler) {
	s.msgHandle.AddRouter(msgId, router...)
}

// 得到连接管理器
func (s *Server) GetConnMgr() interfa.IConnManger {
	return s.ConnMgr
}

// 设置连接开始Hook函数
func (s *Server) SetOnConnStart(hookFunc func(interfa.IConnection)) {
	s.OnConnStart = hookFunc
}

// 设置连接关闭Hook函数
func (s *Server) SetOnConnStop(hookFunc func(interfa.IConnection)) {
	s.OnConnStop = hookFunc
}

// 调用Hook函数
func (s *Server) CallOnConnStart(conn interfa.IConnection) {
	if s.OnConnStart != nil {
		zlog.Debug("---> CallOnConnStart....")
		s.OnConnStart(conn)
	}
}

func (s *Server) CallOnConnStop(conn interfa.IConnection) {
	if s.OnConnStop != nil {
		zlog.Debug("---> CallOnConnStop....")
		s.OnConnStop(conn)
	}
}

func (s *Server) Packet() interfa.IDataPack {
	return s.packet
}

func printServerInfo() {
	zlog.Info("[Zinx] Version ", utils.GlobalObject.Version,
		" MaxConn: ", utils.GlobalObject.MaxConn, " MaxPacketSize: ", utils.GlobalObject.MaxPacketSize,
		" WorkThread: ", utils.GlobalObject.WorkerPoolSize)
}

func init() {

}
